package pers.ljf.escloud.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;

public class BinaryUtils {

    /**
     * 十进制转成二进制后，反转、并变为布尔数组
     *
     * @param val 十进制long
     * @return 转成二进制后，反转、转换成布尔型的数组
     */
    public static boolean[] toReversedBinaryBoolFromLong(Long val) {
        //转二进制
        char[] chars = Long.toBinaryString(val).toCharArray();
        String s = new String(chars);
        //反转
        String reversed = new StringBuilder(s).reverse().toString();
        //遍历字符串转布尔
        int length = reversed.length();
        boolean[] res = new boolean[length];
        for (int i = 0; i < length; i++) {
            if (reversed.charAt(i) == '1')
                res[i] = true;
        }
        return res;
    }

    public static String toReversedBinaryStringFromLong(Long val) {
        //转二进制
        char[] chars = Long.toBinaryString(val).toCharArray();
        String s = new String(chars);
        //反转
        return new StringBuilder(s).reverse().toString();
    }

    public static char[] toReversedBinaryCharsFromLong(Long val, Integer endIndex) {
        //转二进制
        char[] chars = Long.toBinaryString(val).toCharArray();
        int oldLength = chars.length;
        //需要扩容
        if (endIndex >= chars.length) {
            int newLength = endIndex + 1;
            chars = Arrays.copyOf(chars, newLength);
            for (int i = oldLength; i <= newLength - 1; i++) {
                chars[i] = '0';
            }
        }
        String s = new String(chars);
        //反转
        return StringUtils.reverse(s).toCharArray();
    }

    /**
     * @param chars
     * @return
     */

    public static long toLongFromReversedBinaryChars(char[] chars) {
        //反转
        String reverse = StringUtils.reverse(new String(chars));
        //转换
        return Long.parseLong(reverse, 2);
    }

    /**
     * long转指定位数的二进制string
     *
     * @param decNum
     * @param digit
     * @return
     */
    public static String binary2decimal(long decNum, int digit) {
        String binStr = "";
        for (int i = digit - 1; i >= 0; i--) {
            binStr += (decNum >> i) & 1;
        }
        return binStr;
    }

    /**
     * 设置1：x | 0000...1..000,
     * 设置0：x & 1111...0..111,
     * 或运算 0无害，1覆盖，与运算，1无害，0覆盖
     *
     * @param num
     * @param index 从0开始,从num右侧（最低位）开始起
     * @return
     */
    public static Long setBitByIndex(Long num, Integer index, Boolean isOne) {
        Long tmp = isOne ? 1L : 0;
        if (tmp.equals(1L)) {
            Long n = tmp << index;
            //或运算得出结果
            return num | n;
        } else {
            //1111...0...111 = (10000...0...000 - 000...1)[1111...1...111] - 0000..1...000;
            Long n = (Long.MAX_VALUE - (1L << index));
            return num & n;
        }
    }

    /**
     * 得到某位
     * (xxxx...y....xxxx & 0000...1....0000)[0000...y....0000] >> index
     *
     * @param
     */
    public static Long getBitByIndex(Long num, Integer index) {
        //0000...1....0000
        //1000
        Long n = 1L << index;
        //&
        //1010 & 1000
        Long tmp = num & n;
        return tmp >> index;
    }

}
